5.03. Исключения
Исключения
★ Исключения – это события, которые нарушают нормальное выполнение программы. Она может внезапно прекратить работу из-за ошибок в коде, некорректного ввода данных, сбоя в системе и т.д.
Все исключения в Java – это объекты, которые происходят от класса Throwable.
Throwable включает в себя Error и Exception.
Exception включает в себя RuntimeException (unchecked) и checked exceptions.
| Тип | Примеры | Обязательная обработка |
|---|---|---|
| Error | OutOfMemoryError, StackOverflowError | Нет |
| Checked Exceptions | IOException, SQLException | Да |
| Unchecked Exceptions (RuntimeException) | NullPointerException, ArrayIndexOutOfBoundsException | Нет |
Error – серьёзные проблемы, не подлежащие обработке приложением. К примеру, сбой JVM. Эти ошибки не нужно и не рекомендуется перехватывать. Checked Exceptions – проверяемые исключения, которые компилятор требует обработать явно - либо через try-catch, либо через throws, к примеру FileNotFoundException (файл не найден), SQLException (ошибка SQL).
Пример:
public void readFile() throws IOException {
FileReader reader = new FileReader("file.txt");
}
Если метод может выбросить проверяемое исключение, его нужно объявить с ключевым словом throws или обработать внутри метода.
Unchecked Exceptions – непроверяемые исключения, которые являются производными от RuntimeException – компилятор их не проверяет, поэтому можно не обрабатывать – NullPointerException, ArithmeticException, ArrayIndexOutOfBoundsException. Пример:
int result = 10 / 0; // выбросит ArithmeticException
Эти исключения обычно сигнализируют о логических ошибках в коде, и их лучше предотвращать, чем обрабатывать.
Способы для обработки исключений:
- try-catch-finally – блок для перехвата и обработки исключения, по логике «попробуй так, и если поймаешь это, то делай так, и в итоге делай всегда ещё вот так»:
try {
int[] arr = new int[5];
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Ошибка: выход за границы массива");
} finally {
System.out.println("Этот блок выполнится всегда");
}
finally используется для освобождения ресурсов, например, закрытие файла или соединения.
- try-with-resources – автоматически закрывает ресурсы, реализующие интерфейс AutoCloseable:
try (FileReader reader = new FileReader("file.txt")) {
int data = reader.read();
} catch (IOException e) {
e.printStackTrace();
}
- throws указывает, что метод может выбросить исключение, и ответственность за его обработку передаётся вызывающему коду:
public void readData() throws IOException {
FileReader reader = new FileReader("data.txt");
}
Вызывающий код либо сам обрабатывает исключение:
try {
readData();
} catch (IOException e) {
e.printStackTrace();
}
Либо пробрасывает дальше:
public static void main(String[] args) throws IOException {
readData(); // опасно!
}
Чем выше поднимается исключение, тем сложнее обрабатывать. Лучше обрабатывать ближе к источнику ошибки - работа с ошибками - огромная часть функций разработчиков.
Можно использовать инструменты Java и создавать свои классы исключений, расширяя Exception или RuntimeException:
public class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
// или
public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}
Использование:
public void checkAge(int age) throws InvalidAgeException {
if (age < 0) {
throw new InvalidAgeException("Возраст не может быть отрицательным");
}
}